package com.guanzi.netty.test.c1;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

import java.net.InetSocketAddress;

/**
 * @author 管子
 * @date 2025/3/5 20:23
 * @description: HelloClient 类
 */
public class HelloClient {

    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup group = new NioEventLoopGroup();

        // 1、启动类
        ChannelFuture channelFuture = new Bootstrap()
                // 2、添加EventLoop
                .group(group)
                // 3、选择客户端 channel 实现
                .channel(NioSocketChannel.class)
                // 4、添加处理器
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel channel) throws Exception {
                        channel.pipeline().addLast(new StringEncoder());
                        channel.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));
                    }
                })
                // 5、连接服务器 是一个异步非阻塞（指派另一个nio线程，且不等待结果）
                .connect(new InetSocketAddress("localhost", 8080));

        // 1、使用 sync 主线程自己等待 连接建立并发送
        Channel channel = channelFuture
                // 阻塞直到连接建立 (如果连接没建立好就往下走，服务端会收不到信息)
                .sync()
                // 获取连接通道对象
                .channel();

        // 向服务器发送数据
        channel.writeAndFlush("hello, world");

        // 2、使用 addListener 异步处理连接建立并发送
        channelFuture.addListener(new ChannelFutureListener() {
            // 在nio线程连接建立好之后，会调用这个方法
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                Channel channel = channelFuture.channel();
                channel.writeAndFlush("hello, world");
            }
        });

        // 处理关闭，需要用到特殊的close对象
//        channel.close();  直接close会是异步的，会有多线程异步问题
        ChannelFuture closeFuture = channel.closeFuture();

        // 关闭方法1：调用sync之后，会阻塞等待知直到channel的close关闭完成
        channel.close();
        closeFuture.sync();

        // 关闭方法2：
        closeFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                System.out.println("善后工作");
                // 优雅关闭
                group.shutdownGracefully();
            }
        });

    }

}



